
package com.gcloud.mesh.dcs.service;

import com.gcloud.framework.db.PageResult;
import com.gcloud.mesh.asset.service.IAssetService;
import com.gcloud.mesh.dcs.dao.AppProfileDao;
import com.gcloud.mesh.dcs.entity.AppProfileEntity;
import com.gcloud.mesh.header.constant.AppFeatureType;
import com.gcloud.mesh.header.constant.AppSceneType;
import com.gcloud.mesh.header.enums.MonitorMeter;
import com.gcloud.mesh.header.msg.dcs.PageFeatureMsg;
import com.gcloud.mesh.header.msg.dcs.PageSceneMsg;
import com.gcloud.mesh.header.msg.dcs.UpdateProfileFeatureChooseMsg;
import com.gcloud.mesh.header.msg.dcs.UpdateProfileSceneChooseMsg;
import com.gcloud.mesh.header.vo.asset.CountAppProfileVo;
import com.gcloud.mesh.header.vo.asset.DatacenterItemVo;
import com.gcloud.mesh.header.vo.dcs.AppVo;
import com.gcloud.mesh.header.vo.dcs.PageAppFeatureVo;
import com.gcloud.mesh.header.vo.dcs.PageAppProfileVo;
import com.gcloud.mesh.header.vo.dcs.PageAppSceneVo;
import com.gcloud.mesh.monitor.service.StatisticsCheatService;
import com.gcloud.mesh.monitor.service.StatisticsService;
import com.gcloud.mesh.supplier.dao.SupplierDao;
import com.gcloud.mesh.supplier.enums.K8sClusterType;
import com.gcloud.mesh.supplier.enums.SystemType;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.DictCode;
import org.jeecg.common.exception.ParamException;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class AppProfileService {

	@Autowired
	private AppService appService;

	@Autowired
	private StatisticsService statisticsService;

	@Autowired
	private StatisticsCheatService statisticsCheatService;

	@Autowired
	private SupplierDao supplierDao;

	@Autowired
	private IAssetService assetService;

	@Autowired
	private SysDictMapper sysDictMapper;

	@Autowired
	private AppProfileDao dao;

	public void updateFeatureChoose(UpdateProfileFeatureChooseMsg msg) {
		appService.checkAndGet(msg.getAppId());

		if (msg.getFeatureChoose() != null) {
			AppFeatureType secene = AppFeatureType.getByName(msg.getFeatureChoose());
			if (secene == null) {
				throw new ParamException(null, "该业务特点不支持");
			}
		}

		log.info("[{}][App] 开始设置App业务特点：appId={}, featureChoose={}", msg.getMsgId(), msg.getAppId(),
				msg.getFeatureChoose());

		AppProfileEntity profile = dao.getByAppId(msg.getAppId());
		// 记录不存在则新增
		if (profile == null) {
			profile = createNewProfile(msg.getAppId());
		}

		String oldFeatureChoose = profile.getFeatureChoose();
		if (StringUtils.equals(msg.getFeatureChoose(), oldFeatureChoose)) {
			log.info("[{}][App] App业务特点没有变化", msg.getMsgId());
		} else {
			profile.setFeatureChoose(msg.getFeatureChoose());
			dao.update(profile, Lists.newArrayList("featureChoose"));
			log.info("[{}][App] 设置App业务特点成功：appId={}, featureChoose={} -> {}", msg.getMsgId(), msg.getAppId(),
					oldFeatureChoose, msg.getFeatureChoose());
		}
	}

	public void updateSceneChoose(UpdateProfileSceneChooseMsg msg) {
		appService.checkAndGet(msg.getAppId());

		if (msg.getSceneChoose() != null) {
			AppSceneType secene = AppSceneType.getByName(msg.getSceneChoose());
			if (secene == null) {
				throw new ParamException(null, "该应用场景不支持");
			}
		}

		log.info("[{}][App] 开始设置App应用场景：appId={}, sceneChoose={}", msg.getMsgId(), msg.getAppId(),
				msg.getSceneChoose());

		AppProfileEntity profile = dao.getByAppId(msg.getAppId());
		// 记录不存在则新增
		if (profile == null) {
			profile = createNewProfile(msg.getAppId());
		}

		String oldSceneChoose = profile.getSceneChoose();
		if (StringUtils.equals(msg.getSceneChoose(), oldSceneChoose)) {
			log.info("[{}][App] App应用场景没有变化", msg.getMsgId());
		} else {
			profile.setSceneChoose(msg.getSceneChoose());
			dao.update(profile, Lists.newArrayList("sceneChoose"));
			log.info("[{}][App] 设置App应用场景成功：appId={}, sceneChoose={} -> {}", msg.getMsgId(), msg.getAppId(),
					oldSceneChoose, msg.getSceneChoose());
		}
	}

	private AppProfileEntity createNewProfile(String appId) {
		synchronized (AppProfileEntity.class) {
			AppVo app = appService.checkAndGet(appId);
			DatacenterItemVo datacenter = assetService.detailDatacenter(app.getDatacenterId(), "");

			AppProfileEntity profile = dao.getByAppId(appId);
			if (profile == null) {
				profile = new AppProfileEntity();
				profile.setId(UUID.randomUUID().toString());
				profile.setAppId(appId);
				profile.setCreateTime(new Date());
				profile.setDatacenterName(datacenter.getName());
				profile.setFeatureSuggest(appProfileFeatureType(appId));
				profile.setSceneSuggest(appProfileSceneType(appId, null));
				dao.save(profile);
			}
			return profile;
		}
	}

	public void initAppProfile(String appId) {
		AppVo app = appService.checkAndGet(appId);
		String namespaceId = app.getId();
		String clusterId = supplierDao.getConfigValueByDatacenterIdAndConfigName(app.getDatacenterId(),
				SystemType.K8S.getName(), K8sClusterType.CLUSTER_ID.getName());

		AppProfileEntity profile = dao.getByAppId(appId);
		if (profile == null) {
			profile = createNewProfile(appId);
		}

		// PageAppMsg msg = new PageAppMsg();
		// msg.setPageNo(1);
		// msg.setPageSize(9999);
		// PageResult<AppItemVo> apps = appService.page(msg);
		// GceSDK sdk = SpringUtil.getBean(GceSDK.class);
		// GcePageReply<PodVo> vos = sdk.pagePod(clusterId, namespaceId, 1,
		// 999);
		// for (PodVo vo : vos.getData()) {
		// for (AppItemVo vo : apps.getList()) {
		// profile.setFeatureSuggest(appProfileFeatureType(vo.getId()));
		// // profile.setSceneSuggest(appProfileSceneType(vo.getId(),
		// // profile.getFeatureChoose() != null ? profile.getFeatureChoose() :
		// // profile.getFeatureSuggest()));
		// profile.setSceneSuggest(appProfileSceneType(vo.getId(), null));
		// dao.update(profile, Lists.newArrayList("feature_suggest",
		// "scene_suggest"));
		// }

	}

	public PageResult<PageAppProfileVo> pageAppProfile(PageFeatureMsg msg) {
		PageResult<PageAppProfileVo> pages = dao.pageAppProfile(msg.getAppName(), msg.getPageNo(), msg.getPageSize(),
				PageAppProfileVo.class);
		return pages;
	}

	public PageResult<PageAppFeatureVo> pageFeature(PageFeatureMsg msg) {
		String datacenterName = null;
		if (msg.getDatacenterId() != null) {
			DatacenterItemVo datacenter = assetService.getDatacenter(msg.getDatacenterId());
			datacenterName = datacenter.getName();
		}
		PageResult<PageAppFeatureVo> pages = dao.pageFeature(msg.getAppName(), datacenterName, msg.getPageNo(),
				msg.getPageSize(), PageAppFeatureVo.class);
		return pages;
	}

	public PageResult<PageAppSceneVo> pageScene(PageSceneMsg msg) {
		String datacenterName = null;
		if (msg.getDatacenterId() != null) {
			DatacenterItemVo datacenter = assetService.getDatacenter(msg.getDatacenterId());
			datacenterName = datacenter.getName();
		}
		PageResult<PageAppSceneVo> pages = dao.pageScene(msg.getAppName(), datacenterName, msg.getPageNo(),
				msg.getPageSize(), PageAppSceneVo.class);
		return pages;
	}

	public CountAppProfileVo countAppProfile(String datacenterId) {
		DatacenterItemVo datacenter = assetService.getDatacenter(datacenterId);
		String datacenterName = datacenter.getName();

		CountAppProfileVo vo = new CountAppProfileVo();
		int aiNum = 0;
		int cpuNum = 0;
		int ioNum = 0;
		int unknownNum = 0;
		int offlineNum = 0;
		int sequentialNum = 0;
		int realtimeNum = 0;
		PageFeatureMsg msg = new PageFeatureMsg();
		msg.setPageNo(1);
		msg.setPageSize(9999);
		PageResult<PageAppProfileVo> pages = this.pageAppProfile(msg);
		for (PageAppProfileVo appProfile : pages.getList()) {
			if (!datacenterName.equals(appProfile.getDatacenterName())) {
				continue;
			}

			if (appProfile.getFeatureChoose() != null) {
				if (appProfile.getFeatureChoose().equals(AppFeatureType.CPU.name())) {
					cpuNum++;
				} else if (appProfile.getFeatureChoose().equals(AppFeatureType.IO.name())) {
					ioNum++;
				} else if (appProfile.getFeatureChoose().equals(AppFeatureType.AI.name())) {
					aiNum++;
				} else if (appProfile.getFeatureChoose().equals(AppFeatureType.UNKNOWN.name())) {
					unknownNum++;
				}
			} else if (appProfile.getFeatureSuggest() != null) {
				if (appProfile.getFeatureSuggest().equals(AppFeatureType.CPU.name())) {
					cpuNum++;
				} else if (appProfile.getFeatureSuggest().equals(AppFeatureType.IO.name())) {
					ioNum++;
				} else if (appProfile.getFeatureSuggest().equals(AppFeatureType.AI.name())) {
					aiNum++;
				} else if (appProfile.getFeatureSuggest().equals(AppFeatureType.UNKNOWN.name())) {
					unknownNum++;
				}
			}

			if (appProfile.getSceneChoose() != null) {
				if (appProfile.getSceneChoose().equals(AppSceneType.SEQUENTIAL.name())) {
					sequentialNum++;
				} else if (appProfile.getSceneChoose().equals(AppSceneType.REALTIME.name())) {
					realtimeNum++;
				} else if (appProfile.getSceneChoose().equals(AppSceneType.OFFLINE.name())) {
					offlineNum++;
				}
			} else if (appProfile.getSceneSuggest() != null) {
				if (appProfile.getSceneSuggest().equals(AppSceneType.SEQUENTIAL.name())) {
					sequentialNum++;
				} else if (appProfile.getSceneSuggest().equals(AppSceneType.REALTIME.name())) {
					realtimeNum++;
				} else if (appProfile.getSceneSuggest().equals(AppSceneType.OFFLINE.name())) {
					offlineNum++;
				}
			}
		}

		vo.setAiNum(aiNum);
		vo.setCpuNum(cpuNum);
		vo.setIoNum(ioNum);
		vo.setUnknownNum(unknownNum);
		vo.setSequentialNum(sequentialNum);
		vo.setRealtimeNum(realtimeNum);
		vo.setOfflineNum(offlineNum);
		vo.setTotal(sequentialNum + realtimeNum + offlineNum);

		return vo;
	}

	private String appProfileFeatureType(String podName) {
		String appCpuUtilStr = statisticsCheatService.latestSample(MonitorMeter.APP_CPU_UTIL.getMeter(), podName);
		String appReadRateStr = statisticsCheatService.latestSample(MonitorMeter.APP_FS_READS_RATE.getMeter(), podName);
		String appWriteRateStr = statisticsCheatService.latestSample(MonitorMeter.APP_FS_WRITES_RATE.getMeter(),
				podName);

		Double cpuBaseline = Double.valueOf(appCpuUtilStr);
		Double fsReadBaseline = Double.valueOf(appReadRateStr);
		Double fsWriteBaseline = Double.valueOf(appWriteRateStr);

		if (cpuBaseline > 60) {
			if (fsReadBaseline > 200 * 1024) {
				return AppFeatureType.AI.name();
			}
			return AppFeatureType.CPU.name();
		}
		if (fsWriteBaseline > 100 * 1024) {
			return AppFeatureType.IO.name();
		}

		return AppFeatureType.IO.name();
	}

	private String appProfileSceneType(String podName, String appFeatureType) {

		List<DictModel> dicts = sysDictMapper.queryDictItemsByCode(DictCode.MONITOR_STATISTICS_CONFIG.getCode());
		if (dicts != null) {
			for (DictModel dict : dicts) {
				int type = Integer.parseInt(dict.getValue());
				if (type == 0) {
					return AppSceneType.SEQUENTIAL.name();
				} else if (type == 1) {
					return AppSceneType.REALTIME.name();
				} else if (type == 2) {
					return AppSceneType.OFFLINE.name();
				}
			}
		}

		// StatisticsMsg msg = new StatisticsMsg();
		// msg.setResourceId(podName);
		// String appMetircStr;
		//
		// if (appFeatureType.equals("CPU")) {
		// appMetircStr =
		// statisticsCheatService.latestSample(MonitorMeter.APP_CPU_UTIL.getMeter(),
		// podName);
		// msg.setMeter(MonitorMeter.APP_CPU_UTIL.getMeter());
		// } else if (appFeatureType.equals("IO")) {
		// appMetircStr =
		// statisticsCheatService.latestSample(MonitorMeter.APP_FS_READS_RATE.getMeter(),
		// podName);
		// msg.setMeter(MonitorMeter.APP_FS_READS_RATE.getMeter());
		// } else {
		// return AppSceneType.OFFLINE.name();
		// }
		//
		// // 以6个小时为节点，拿到一天以内的4个数据点，根据这4个数据点来判断应用场景特点
		// Date beforeByQuarterDay = TimestampUtil.BeforeHourNow(6);
		// Date beforeByHalfDay = TimestampUtil.BeforeHourNow(12);
		// Date beforeByThreeQuaeterDay = TimestampUtil.BeforeHourNow(18);
		// Date beforeByOneDay = TimestampUtil.BeforeHourNow(24);
		//
		// msg.setBeginTime(TimestampUtil.dateToStr(TimestampUtil.BeforeSecondDate(beforeByQuarterDay,
		// 60)));
		// msg.setEndTime(TimestampUtil.dateToStr(beforeByQuarterDay));
		// StatisticsVo alpha = statisticsCheatService.statistics(msg);
		//
		// msg.setBeginTime(TimestampUtil.dateToStr(TimestampUtil.BeforeSecondDate(beforeByHalfDay,
		// 60)));
		// msg.setEndTime(TimestampUtil.dateToStr(beforeByHalfDay));
		// StatisticsVo beta = statisticsCheatService.statistics(msg);
		//
		// msg.setBeginTime(TimestampUtil.dateToStr(TimestampUtil.BeforeSecondDate(beforeByThreeQuaeterDay,
		// 60)));
		// msg.setEndTime(TimestampUtil.dateToStr(beforeByThreeQuaeterDay));
		// StatisticsVo gamma = statisticsCheatService.statistics(msg);
		//
		// msg.setBeginTime(TimestampUtil.dateToStr(TimestampUtil.BeforeSecondDate(beforeByOneDay,
		// 60)));
		// msg.setEndTime(TimestampUtil.dateToStr(beforeByOneDay));
		// StatisticsVo delte = statisticsCheatService.statistics(msg);
		//
		// Double x = alpha.getList().get(0).getPoints().get(0).getValue();
		// Double y = beta.getList().get(0).getPoints().get(0).getValue();
		// Double z = gamma.getList().get(0).getPoints().get(0).getValue();
		// Double w = delte.getList().get(0).getPoints().get(0).getValue();
		//
		// Double baseline = Double.valueOf(appMetircStr);
		// if ((x >= baseline && y >= baseline && z >= baseline && w >=
		// baseline)
		// || (x < baseline && y < baseline && z < baseline && w < baseline)) {
		// return AppSceneType.SEQUENTIAL.name();
		// } else if ((x >= baseline && y < baseline && z < baseline && w >=
		// baseline)
		// || (x < baseline && y >= baseline && z >= baseline && w < baseline))
		// {
		// return AppSceneType.REALTIME.name();
		// } else {
		// return AppSceneType.OFFLINE.name();
		// }
		return AppSceneType.SEQUENTIAL.name();
	}

}
